#!/usr/bin/perl
#Written by Lu Wang(Lu.Wang@ihep.ac.cn)
#It should be called clienthealty.pl 
#Version V1.0

 
$SMALLEXT=7; # means the thredhold is  4K*(2^$(thredhold))
$LOWEFF=80; #concerns only the processes whose efficiency is lower than $ethredhold
$MAX_CACHED_MB=8192;

$touser="ics\@ihep.ac.cn";
$debug=1;
$period=10;
$logfile="/tmp/ralog";
if ($#ARGV<0){
	$period=60;
}else{
	$period=$ARGV[0];
}

$hostname=`hostname`;
$nt=`date`;
chomp($nt);
chomp($hostname);
$mailstring="At $nt on $hostname";
print "$mailstring\n";

@procres=</proc/fs/lustre/llite/*>;
for $i(@procres){
	$topdir=$i;
	$i=~s/(.*)\/(\w+)-(.*)/$2/;
	print "\nReport of $i\n";
	&rs_fs($topdir,$mailstring);
	&r_process($topdir,$mailstring);
}

sub resetra(){
	my ($topdir)=@_;
	`echo 0 > $topdir/max_read_ahead_per_file_mb`;
	`echo 0 > $topdir/max_read_ahead_whole_mb`;
	`echo 1 > $topdir/max_read_ahead_per_file_mb`;
	`echo 1 > $topdir/max_read_ahead_whole_mb`;
	print "echo 0 > $topdir/max_read_ahead_per_file_mb\n";
}
sub rs_fs(){
	print "\tStep 1: Check the status of file system\n";
	my ($topdir,$mailstring)=@_;
	$string="\t\t";
	#Step 1.1: Report and Set max_cached_mb 
        my $oldvalue=`cat $topdir/max_cached_mb`;
        chomp($oldvalue);
        `echo 0 > $topdir/read_ahead_stats`;
        `sleep 10`;
        open STAT, "$topdir/read_ahead_stats";
        while(<STAT>){
                if ($_ =~ /discarded/){
			$string.="LOWCACHE:";
                        my $value=$oldvalue*2;
                        if ($value >$MAX_CACHED_MB){
                                $string .=" max cache size reached for $topdir\n";
                        }else{
                                $string .=" cache enlarged to  $value\n";
                                `echo $value >$topdir/max_cached_mb`;
                        }
                        print "$string";
                        return;
                }
        }
	close STAT;
	$string.="ENOUGHCACHE:$oldvalue\n";
	print "$string";
	return;
}
sub r_process(){
	print "\tStep 2: Report by Process\n";
	my ($topdir,$mailstring)=@_;
	$enterp="$topdir/extents_stats";
        $content="$topdir/extents_stats_per_process";
	$found=0;
	@tmp=();
	`echo 1 > $enterp`;
	if ($?){
		exit -1;
	}
	`sleep $period`;
	open FIN,"$content" or die "Can not open proc entry:$!\n";
	while(<FIN>){
		if ($found==1){
			unless(/^(\s*)$/){
				push (@tmp,$_);
				next;
			}
			$found=0;
			&anapid(\@tmp,$pid);
		}else{
			if (/PID:(\s+)(\d+)/){
				$found=1;
				$pid=$2;
				@tmp=();
			}
		}		
	}
	&anapid(\@tmp,$pid);
	`echo 0 > $enterp`;
	close FIN;
}
sub anapid(){
	my ($resref,$pid)=@_;
	my $username;
	$printspace="\t\t";
	print "$printspace";
	print "===Process $pid===\n";

	# Step 2.1: Report efficiency 
	my $pcpu=`ps -p $pid -opcpu= 2>/dev/null`;
	my $uid=`ps -p $pid -ouid= 2>/dev/null`;
	my $cmd=`ps -p $pid -ocmd= 2>/dev/null`;
	chomp($pcpu);
	chomp($uid);	
	if ($?){
		print "$printspace";
		print "Not exists process $pid\n";
		return 0;
	}
	if ($uid ==0){
		print "$printspaceSKIP:skip root process\n";
		return 0;
	}else{
		$username=&finduser($uid);	
	}
	print "$printspace";
	if ($pcpu>$LOWEFF){
			print "EFFICIENT:";
	}else{
			print "LOWEFFICIENT:"	
	}
	print "process: $pid  efficiency: $pcpu user: $username command: $cmd\n";
	
	# Step 2.2: Report IO pattern
	$power=0;
	while($resref->[$power]){
		$power++;
	}
	print "$printspace";
	if ($power==0){
		print "UNKNOWN:Do not have encough sample for $pid\n";
		return 0;
	}
	
	if ($power<$SMALLEXT){
		$s=$resref->[$power-1];
		@r=split (/\s+/,$s);
		if ($r[6]>0){
			print "BADIO:$printspace$resref->[$power-1]\n";
			return 0;
		}
	}

	print "GOODIO:$printspace$resref->[$power-1]\n";
	return 0;
}

sub finduser(){
	my ($uid)=@_;
	$res=`grep $uid /etc/passwd`;
	@r=split /:/,$res;
	return $r[0];
}


